package com.ruoyi.web.xxj.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import javax.annotation.Resource;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.xxj.domain.ClassInfo;
import com.ruoyi.web.xxj.domain.ClassOrder;
import com.ruoyi.web.xxj.domain.ClassType;
import com.ruoyi.web.xxj.domain.pojo.PrePayReq;
import com.ruoyi.web.xxj.domain.pojo.WxPayV3Bean;
import com.ruoyi.web.xxj.domain.vo.ClassOrderVo;
import com.ruoyi.web.xxj.domain.vo.EachMonthCountObj;
import com.ruoyi.web.xxj.enums.Constants;
import com.ruoyi.web.xxj.enums.PayStatus;
import com.ruoyi.web.xxj.mapper.ClassOrderMapper;
import com.ruoyi.web.xxj.service.IClassOrderService;
import com.ruoyi.web.xxj.service.IClassTypeService;
import com.ruoyi.web.xxj.util.UniqueOrderNumberGenerator;

import com.wechat.pay.java.core.http.Constant;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import com.wechat.pay.java.service.refund.model.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.method.P;
import org.springframework.stereotype.Service;

/**
 * 课程订单Service业务层处理
 *
 * @author ruoyi
 * @date 2024-01-25
 */
@Service
public class ClassOrderServiceImpl implements IClassOrderService {

    private static final Logger log = LoggerFactory.getLogger(ClassOrderServiceImpl.class);

    @Resource
    private WxPayV3Bean wxPayV3Bean;
    @Autowired
    private ClassOrderMapper classOrderMapper;
    @Autowired
    private ClassInfoServiceImpl classInfoService;
    @Autowired
    private IClassTypeService classTypeService;

    /**
     * 查询课程订单
     *
     * @param id 课程订单主键
     * @return 课程订单
     */
    @Override
    public ClassOrderVo selectClassOrderById(Long id) {
        return classOrderMapper.selectClassOrderById(id);
    }

    /**
     * 查询课程订单
     *
     * @param orderNo 课程订单订单号
     * @return 课程订单
     */
    @Override
    public ClassOrderVo selectClassOrderByOrderNo(String orderNo) {
        return classOrderMapper.selectClassOrderByOrderNo(orderNo);
    }

    /**
     * 查询课程订单列表
     *
     * @param classOrder 课程订单
     * @return 课程订单
     */
    @Override
    public List<ClassOrderVo> selectClassOrderList(ClassOrder classOrder) {
        return classOrderMapper.selectClassOrderList(classOrder);
    }

    /**
     * 新增课程订单
     *
     * @param classOrder 课程订单
     * @return 结果
     */
    @Override
    public int insertClassOrder(ClassOrder classOrder) {
        classOrder.setCreateTime(DateUtils.getNowDate());
        return classOrderMapper.insertClassOrder(classOrder);

        //调支付接口
    }

    /**
     * 修改课程订单
     *
     * @param classOrder 课程订单
     * @return 结果
     */
    @Override
    public int updateClassOrder(ClassOrder classOrder) {
        classOrder.setUpdateTime(DateUtils.getNowDate());
        return classOrderMapper.updateClassOrder(classOrder);
    }

    /**
     * 批量删除课程订单
     *
     * @param ids 需要删除的课程订单主键
     * @return 结果
     */
    @Override
    public int deleteClassOrderByIds(Long[] ids) {
        return classOrderMapper.deleteClassOrderByIds(ids);
    }

    /**
     * 删除课程订单信息
     *
     * @param id 课程订单主键
     * @return 结果
     */
    @Override
    public int deleteClassOrderById(Long id) {
        return classOrderMapper.deleteClassOrderById(id);
    }

    /**
     * 取消订单课程
     *
     * @param id
     * @return
     */
    @Override
    public int cancel(Long id, String cancelReason) {

        ClassOrder order = classOrderMapper.selectClassOrderById(id);

        this.compareWechatuserId(order.getWechatUserid());

        log.info("客户ID[" + SecurityUtils.getLoginUser().getWechatUser().getId() +
                "]申请取消课程订单,订单ID[" + id + "],课程ID[" + order.getClassId() + "],课程名称[" + order.getClassName() + "");

        //未支付可直接取消，已支付就得审核
        if (order.getPayStatus().equals(PayStatus.NOPAID.getValue())) {
            order.setPayStatus(PayStatus.CANCEL.getValue());
        } else {
            //生成商户退款订单号
            String outRefundNo = Constants.OrderNo_Prefix.C.name() + System.currentTimeMillis();
            order.setPayStatus(PayStatus.REFUND_TO_AUDIT.getValue());
            order.setRefundNo(outRefundNo);
        }
        order.setCancelReason(cancelReason);
        order.setRemark("取消订单");
        return this.updateClassOrder(order);
    }


    @Override
    public int withdraw(Long id) {

        ClassOrder order = this.selectClassOrderById(id);
        this.compareWechatuserId(order.getWechatUserid());
        if (!order.getPayStatus().equals(PayStatus.REFUND_TO_AUDIT.getValue())) {
            log.info("课程订单主键ID[" + id + "]，课程订单状态为[" + PayStatus.getNameByValue(order.getPayStatus()) + "]");
            throw new ServiceException("订单状态为非退款待审核状态，无法撤销订单取消申请！");
        }
        order.setPayStatus(PayStatus.PAIDED.getValue());
        order.setUpdateBy(SecurityUtils.getLoginUser().getWechatUser().getNickname());
        order.setUpdateTime(DateUtils.getNowDate());
        return classOrderMapper.updateClassOrder(order);
    }

    private void compareWechatuserId(Long wechatuserId) {
        if (!SecurityUtils.getLoginUser().getWechatUser().getId().equals(wechatuserId)) {
            log.info("当前用户ID[" + SecurityUtils.getLoginUser().getWechatUser().getId() + "]，订单用户ID[" + wechatuserId + "]");
            throw new ServiceException("订单用户不一致，不允许取消他人订单！");
        }
    }

    @Override
    public Integer getToYearClassOrderCount() {
        return classOrderMapper.getToYearClassOrderCount();
    }

    @Override
    public List<EachMonthCountObj> getEachMonthClassOrderNum() {
        return classOrderMapper.getEachMonthClassOrderNum();
    }

    public ClassOrder createOrder(PrePayReq prePayVo, Long weChatUserId) {
        if (Objects.isNull(prePayVo.getClassOrderReq())) {
            return null;
        }

        ClassInfo classInfo = classInfoService.selectClassInfoById(prePayVo.getClassOrderReq().getClassId());
        ClassType classType = classTypeService.selectClassTypeById(classInfo.getType());
        if (classType.getTypeName().contains("学校研学")) {
            checkExist(prePayVo.getClassOrderReq());
		}
        ClassOrder classOrder = new ClassOrder();
        BeanUtils.copyProperties(prePayVo.getClassOrderReq(), classOrder);
        classOrder.setWechatUserid(weChatUserId);
        classOrder.setOrderNo(Constants.OrderNo_Prefix.C.name() + System.currentTimeMillis());

        classOrder.setPayAmount(classInfo.getPrice());
        classOrder.setPayStatus(PayStatus.NOPAID.getValue());
        classOrder.setCreateTime(DateUtils.getNowDate());
        classOrder.setUpdateTime(DateUtils.getNowDate());
        classOrderMapper.insertClassOrder(classOrder);
        return classOrder;
    }

    private void checkExist(PrePayReq.ClassOrderReq classOrderReq) {
        ClassOrder classOrder = new ClassOrder();
        classOrder.setClassId(classOrderReq.getClassId());
        classOrder.setChildSchool(classOrderReq.getChildSchool());
        classOrder.setChildGrade(classOrderReq.getChildGrade());
        classOrder.setChildClass(classOrderReq.getChildClass());
        classOrder.setChildName(classOrderReq.getChildName());
        classOrder.setChildIdcard(classOrderReq.getChildIdcard());
        classOrder.setPayStatus(PayStatus.PAIDED.getValue());
        List<ClassOrderVo> classOrders = classOrderMapper.selectClassOrderList(classOrder);
        if (Objects.nonNull(classOrders) && !classOrders.isEmpty()) {
            throw new IllegalArgumentException("该学生已报名！");
        }
    }

    public void processOrder(String orderNo, Transaction transaction) {
        ClassOrder classOrder = classOrderMapper.selectClassOrderByOrderNo(orderNo);
        if (StringUtils.equals(classOrder.getPayStatus(), PayStatus.PAIDED.getValue())) {
            log.warn("重复回调 该订单已处理！！！！");
            return;
        }
        classOrder.setPayStatus(PayStatus.PAIDED.getValue());
        classOrder.setUpdateTime(new Date());
        classOrder.setWxpayTradeNo(transaction.getOutTradeNo());
        classOrderMapper.updateClassOrder(classOrder);
    }

    public void processRefund(String orderNo, RefundNotification refundNotification) {
        ClassOrder classOrder = classOrderMapper.selectClassOrderByOrderNo(orderNo);
        if (StringUtils.equals(classOrder.getPayStatus(), PayStatus.REFUNDED.getValue())
                || StringUtils.equals(classOrder.getPayStatus(), PayStatus.REFUND_FAIL.getValue())) {
            log.warn("重复回调 该订单已处理！！！！");
            return;
        }
        if (StringUtils.equalsIgnoreCase(refundNotification.getRefundStatus().name(), Status.SUCCESS.name())) {
            classOrder.setPayStatus(PayStatus.REFUNDED.getValue());
        } else if (StringUtils.equalsIgnoreCase(refundNotification.getRefundStatus().name(), Status.ABNORMAL.name())) {
            classOrder.setPayStatus(PayStatus.REFUND_FAIL.getValue());
        }
        classOrder.setRefundNo(refundNotification.getOutRefundNo());
        classOrder.setUpdateTime(new Date());
        classOrderMapper.updateClassOrder(classOrder);
    }
}
